import CommunicationManager from "./CommunicationManager";
import SerialPortManager from "./SerialPortManager";
import DataCenter from "./DataCenter";
import { ProductID, Topic_Control, Topic_Loop_Reply, Topic_Strategy_Reply, Topic_Tunnel_Reply, Topic_UpdateIp, Topic_Property, Topic_Control_Reply, Topic_Adjust, ACK_Type, Control_Level, Topic_UpdateIp_Reply, Topic_Master, Topic_Update_LightMode, Topic_Update_LightMode_Reply, Topic_Master_Reply, Topic_Debug, Adjust_Model, Topic_Strategy, Topic_Tunnel, Topic_Loop, Topic_Async, Topic_Async_Reply, Topic_Update_Meter_Config, Topic_Update_Meter_Config_Reply, Topic_Meter_Property, ValidType } from "./LogicConstant";
import XLog from "../libs/XLog";
import { commonMakeRsp2Request, commonMakeMqttRequest, commonMakeControlData, commonMakeParams, transControl2Adjust, commonMakeGateBrightControlCmd, commonMakeGateStrategyControlCmd, commonMakeControlRequest, commonMakeMeterRequest } from "./Utils";
import { formatterSendTopic, formatterTopic } from "./TopicUtil";
import StrategyManager from "./StrategyManager";
import AsyncDataManager from "./AsyncDataManager";
import { DeviceEventEmitter } from "react-native";
import {MeterQueryType} from "../libs/SerialCommon";
import {parserSmartMeter} from "../libs/SerialMeterParser";

export default class CommandManager {
    static installCommandLogic() {
        this.installRemoteMqttCommand();
        this.installLocalMqttCommand();
    }

    static installRemoteMqttCommand() {
        CommunicationManager.onRemoteMqttEvent(
            Topic_Control.method,
            this.onRemoteMqttControl
        );
        CommunicationManager.onRemoteMqttEvent(
            Topic_Strategy_Reply.method,
            this.onRemoteMqttStrategyReply
        );
        CommunicationManager.onRemoteMqttEvent(
            Topic_Tunnel_Reply.method,
            this.onRemoteMqttTunnelReply
        );
        CommunicationManager.onRemoteMqttEvent(
            Topic_Loop_Reply.method,
            this.onRemoteMqttLoopReply
        );
        CommunicationManager.onRemoteMqttEvent(
            Topic_UpdateIp.method,
            this.onRemoteMqttUpdateServerIp
        );
        CommunicationManager.onRemoteMqttEvent(
            Topic_Master_Reply.method,
            this.onRemoteMqttUpdateMaster
        );
        CommunicationManager.onRemoteMqttEvent(
            Topic_Update_LightMode.method,
            this.onRemoteMqttLightMode
        );
        CommunicationManager.onRemoteMqttEvent(
            Topic_Debug.method,
            this.onUpdateMqttDebugOperation
        );
        CommunicationManager.onRemoteMqttEvent(
            Topic_Update_Meter_Config.method,
            this.onUpdateMqttMeterConfig
        );
    }

    static installLocalMqttCommand() {
        CommunicationManager.onLocalMqttEvent(
            Topic_Control.method,
            this.onLocalMqttControl
        );
        CommunicationManager.onLocalMqttEvent(
            Topic_Strategy_Reply.method,
            this.onLocalMqttStrategyReply
        );
        CommunicationManager.onLocalMqttEvent(
            Topic_Tunnel_Reply.method,
            this.onLocalMqttTunnelReply
        );
        CommunicationManager.onLocalMqttEvent(
            Topic_Loop_Reply.method,
            this.onLocalMqttLoopReply
        );
        CommunicationManager.onLocalMqttEvent(
            Topic_Strategy.method,
            this.onLocalMqttStrategy
        );
        CommunicationManager.onLocalMqttEvent(
            Topic_Tunnel.method,
            this.onLocalMqttTunnel
        );
        CommunicationManager.onLocalMqttEvent(
            Topic_Loop.method,
            this.onLocalMqttLoop
        );
        CommunicationManager.onLocalMqttEvent(
            Topic_Async.method,
            this.onLocalMqttAsync
        );
        CommunicationManager.onLocalMqttEvent(
            Topic_Async_Reply.method,
            this.onLocalMqttAsyncReply
        );
        // CommunicationManager.onLocalMqttEvent(
        //     Topic_Update_LightMode.method,
        //     this.onLocalMqttLightMode
        // );

        CommunicationManager.onLocalMqttEvent(
            Topic_Property.method,
            this.onUpdateMqttProperty
        );
    }

    static installSerialEvent(){
        SerialPortManager.addSerialEvent(
            "readAddress",
            this.onQueryDeviceAddress
        );

        SerialPortManager.addSerialEvent(
            "setLampState",
            this.onSetLampState
        );

        SerialPortManager.addSerialEvent(
            "setLampLight",
            this.onSetLampLight
        );

        SerialPortManager.addSerialEvent(
            "readLight",
            this.onQueryDeviceInfo
        );

        SerialPortManager.addSerialEvent(
            "timeout",
            this.onSerialTimeout
        );

        SerialPortManager.addSerialEvent(
            "realtime",
            this.onMeterRealtime
        );

        SerialPortManager.addSerialEvent(
            "stat",
            this.onMeterStat
        );
    }

    static onRemoteMqttControl(data) {
        try{
            XLog.d("onRemoteMqttControl", data);
            //收到远程控制指令，自己操作自己，控制是回路级别的
            // 1. 执行操作 2. 发送control给master 3. 发送control_reply给remote
            if(!data || !data.control || data.control.length <= 0) {
                return;
            }
            if(DataCenter.gateId != data.gateId) {
                XLog.e("onRemoteMqttControl gateId not equal:", DataCenter.gateId, data.gateId);
                return;
            }
            let control_cmd = [];
            for(let controlItem of data.control) {
                if(controlItem.strategyId == 0) {//调光
                    // console.log("onRemoteMqttControl ", controlItem);
                    control_cmd.push(commonMakeGateBrightControlCmd(controlItem.loopNumber, controlItem.brightness));
                    SerialPortManager.controlLight(controlItem.loopNumber, controlItem.brightness);
                    DataCenter.setColonyCabinetDeviceLight(DataCenter.gateId, [controlItem.loopNumber], controlItem.brightness);
                    DataCenter.setSegmentCabinetDeviceLightByGateId(controlItem.gateId, [controlItem.loopNumber], controlItem.brightness);
                } else {
                    control_cmd.push(commonMakeGateStrategyControlCmd(controlItem.loopNumber, controlItem.strategyId));
                    DataCenter.setColonyCabinetDeviceStrategyId(DataCenter.gateId, [controlItem.loopNumber], controlItem.strategyId);
                    DataCenter.setSegmentCabinetDeviceStrategyByGateId(controlItem.gateId, [controlItem.loopNumber], controlItem.strategyId);
                }                
            }
            SerialPortManager.controlLightEnd();
            DeviceEventEmitter.emit("localCabinet");
            DeviceEventEmitter.emit("tunnelCabinet");
            CommunicationManager.send2Master(formatterSendTopic(Topic_Control), 
                commonMakeControlRequest(
                    Control_Level.LEVEL_LOOP,
                    true,
                    0, DataCenter.gateId, 
                    Adjust_Model.ADJUST_DIRECT_LIGHT, "", control_cmd, false
                ));
            CommunicationManager.send2Remote(formatterTopic(Topic_Control_Reply, DataCenter.serverId, DataCenter.gateId, ProductID.LOOP),
                commonMakeRsp2Request(commonMakeControlData(data.control), Topic_Control_Reply.method));
        }catch(error) {
            XLog.e("onRemoteMqttControl exception:",error?.message);
        }
    }

    static async onRemoteMqttStrategyReply(data) {
        //远程收到策略更新，判断是否是master，转发
        // console.time("onRemoteMqttStrategyReply");
        try{
            console.log("onRemoteMqttStrategyReply", data);
            if(DataCenter.isMaster) {
                DataCenter.setStrategyList(data);
                CommunicationManager.send2Master(formatterSendTopic(Topic_Strategy_Reply),
                    commonMakeRsp2Request(data, Topic_Strategy_Reply.method));
            } else {
                XLog.e("onRemoteMqttStrategyReply not master");
            }
        }catch(error) {
            XLog.e("onRemoteMqttStrategyReply exception:",error?.message);
        }
        // console.timeEnd("onRemoteMqttStrategyReply");
    }

    static onRemoteMqttTunnelReply(data) {
        //远程收到单洞数据更新，判断是否是master，转发
        // console.time("onRemoteMqttTunnelReply");
        try{
            console.log("onRemoteMqttTunnelReply", data);
            if(DataCenter.isMaster) {
                DataCenter.setTunnelGates(data);
                CommunicationManager.send2Master(formatterSendTopic(Topic_Tunnel_Reply),
                commonMakeRsp2Request(data, Topic_Tunnel_Reply.method));
            } else {
                XLog.e("onRemoteMqttTunnelReply not master");
            }
        }catch(error) {
            XLog.e("onRemoteMqttTunnelReply exception:",error?.message);
        }
        
        // console.timeEnd("onRemoteMqttTunnelReply");
    }

    static onRemoteMqttLoopReply(data) {
        //远程收到集群数据更新，判断是否是master，转发
        // console.time("onRemoteMqttLoopReply");
        try{
            console.log("onRemoteMqttLoopReply", data);
            if(DataCenter.isMaster) {
                DataCenter.setColonyGates(data);
                CommunicationManager.send2Master(formatterSendTopic(Topic_Loop_Reply),
                commonMakeRsp2Request(data, Topic_Loop_Reply.method));
            } else {
                XLog.e("onRemoteMqttLoopReply not master");
            }
        }catch(error) {
            XLog.e("onRemoteMqttLoopReply exception:",error?.message);
        }
        
        // console.timeEnd("onRemoteMqttLoopReply");
    }

    static async onRemoteMqttUpdateServerIp(data) {
        try{
            console.log("onRemoteMqttUpdateServerIp: ", data);
            if(data.serverIp == DataCenter.serverIp && data.serverId == DataCenter.serverId) {
                CommunicationManager.send2Remote(formatterSendTopic(Topic_UpdateIp_Reply),
                commonMakeRsp2Request(1, Topic_UpdateIp_Reply.method));
            } else {
                DataCenter.updateServerIP(data.gateId, data.serverIp, data.serverId);
                await CommunicationManager.destroyRemoteMqttClient();
                await CommunicationManager.createRemoteMqttClient();
                CommunicationManager.send2Remote(formatterSendTopic(Topic_UpdateIp_Reply),
                    commonMakeRsp2Request(1, Topic_UpdateIp_Reply.method));
            }
        }catch(error) {
            XLog.e("onRemoteMqttUpdateServerIp exception:",error?.message);
        }
    }

    static async onRemoteMqttUpdateMaster(data) {
        try{
            console.log("onRemoteMqttUpdateMaster", data);
            if((DataCenter.masterId != data.gateId)) {//说明主控变了
                if(DataCenter.isMaster) {//如果我以前是主控且现在不是了
                   await CommunicationManager.destroyMqttServer();
                }
                await CommunicationManager.destroyLocalMqttClient();
                DataCenter.updateMaster(data.gateId, data.gateIp, data.gateSecret);
                if(data.gateId == DataCenter.gateId) {//我变成了主控
                    await CommunicationManager.createMqttServer();
                }
                await CommunicationManager.createLocalMqttClient();
            } else if(DataCenter.masterIp != data.gateIp && !DataCenter.isMaster) {//只是主控ip变了
                await CommunicationManager.destroyLocalMqttClient();
                DataCenter.updateMaster(data.gateId, data.gateIp, data.gateSecret);
                await CommunicationManager.createLocalMqttClient();
            }
        }catch(error) {
            XLog.e("onRemoteMqttUpdateMaster exception:",error?.message);
        }
    }

    static onLocalMqttControl(data) {
        //1. 如果本机是master，则根据control是否更新缓存，决定是否发送给远程服务器
        //2. 非本机发送的消息，则根据constrol是否更新缓存，决定是否更新本机缓存
        //3. 如果收到的消息是段控制消息，则查询本机是否在段中
        // console.time("onLocalMqttControl");
        try{
            console.log("onLocalMqttControl", data);
            if(!data) {
                return;
            }
            if(DataCenter.isMaster && data.needCache && data.needAdjust) {
                CommunicationManager.send2Remote(formatterSendTopic(Topic_Adjust),
                commonMakeMqttRequest(ACK_Type.ACK, transControl2Adjust(data), Topic_Adjust.method));
            }
            if(CommandManager.isSelfSendMessage(data)) {
                return;
            }
            //检查是否是段消息
            if(data.controlType == Control_Level.LEVEL_SEGMENT && data.sectionId) {
                let loops = DataCenter.queryLoopsInSection(data.sectionId);
                for(var item of loops.local){
                    //去掉策略
                    if(data.strategyId == 0) {//调光
                        SerialPortManager.controlLight(item, data.brightness);
                    }
                }
                if(data.needCache) {//需要缓存
                    if(data.strategyId == 0) {//调光
                        DataCenter.setColonyCabinetDeviceLight(DataCenter.gateId, loops.local, data.brightness);
                        for(let gate of Object.keys(loops.colony)) {
                            DataCenter.setColonyCabinetDeviceLight(gate, loops.colony[gate], data.brightness);
                        }
                        DataCenter.setSegmentCabinetDeviceLight(data.sectionId, data.brightness);
                    } else {
                        DataCenter.setColonyCabinetDeviceStrategyId(DataCenter.gateId, loops.local, data.strategyId);
                        for(let gate of Object.keys(loops.colony)) {
                            DataCenter.setColonyCabinetDeviceStrategyId(gate, loops.colony[gate], data.strategyId);
                        }
                        DataCenter.setSegmentCabinetDeviceStrategyId(data.sectionId, data.strategyId);
                    }
                }
            } else if(data.controlType == Control_Level.LEVEL_LOOP && data.controlGateId) {
                for(let controlItem of data.control||[]) {
                    if(DataCenter.gateId == data.controlGateId) {//控制我
                        if(controlItem.strategyId == 0) {//调光
                            SerialPortManager.controlLight(controlItem.loopNumber, controlItem.brightness);
                        }
                    } 
                    if(data.needCache) {
                        if(controlItem.strategyId == 0) {//调光
                            DataCenter.setColonyCabinetDeviceLight(data.controlGateId, [controlItem.loopNumber], controlItem.brightness);
                            DataCenter.setSegmentCabinetDeviceLightByGateId(data.controlGateId, [controlItem.loopNumber], controlItem.brightness);
                        } else {
                            DataCenter.setColonyCabinetDeviceStrategyId(data.controlGateId, [controlItem.loopNumber], controlItem.strategyId);
                            DataCenter.setSegmentCabinetDeviceStrategyByGateId(data.controlGateId, [controlItem.loopNumber], controlItem.strategyId);                    
                        }
                    }
                }
            } else if(data.controlType == Control_Level.LEVEL_STRATEGY) {
                for(let controlItem of data.control||[]) {
                    DataCenter.setColonyCabinetDeviceLight(data.controlGateId, [controlItem.loopNumber], controlItem.brightness, false);
                }
            }
            SerialPortManager.controlLightEnd();
            DeviceEventEmitter.emit("localCabinet");
            DeviceEventEmitter.emit("colonyCabinet");
            DeviceEventEmitter.emit("tunnelCabinet");
        }catch(error) {
            XLog.e("onLocalMqttControl exception:",error?.message);
        }
        // console.timeEnd("onLocalMqttControl");
    }

    static async onLocalMqttStrategyReply(data) {
        //本地收到策略更新，更新本地缓存
        try{
            console.log("onLocalMqttStrategyReply", data);
            DataCenter.setStrategyList(data);
        }catch(error) {
            XLog.e("onLocalMqttStrategyReply exception:",error?.message);
        }
    }

    static onLocalMqttTunnelReply(data) {
        //本地收到单洞数据更新，更新本地缓存
        try{
            console.log("onLocalMqttTunnelReply", data);
            DataCenter.setTunnelGates(data);
        }catch(error) {
            XLog.e("onLocalMqttTunnelReply exception:",error?.message);
        }
    }

    static onLocalMqttLoopReply(data) {
        //本地收到集群数据更新，更新本地缓存
        try{
            console.log("onLocalMqttLoopReply", data);
            DataCenter.setColonyGates(data);
        }catch(error) {
            XLog.e("onLocalMqttLoopReply exception:",error?.message);
        }
    }

    // Serial Port callback functions
    static onQueryDeviceAddress(data){
        XLog.i("onQueryDeviceAddress data: " + JSON.stringify(data));
    }

    static onSetLampLight(data){
        // DataCenter.setLightLight(data);
        XLog.i("onSetLampLight data: " + JSON.stringify(data));
    }

    static onSetLampState(data){
        // DataCenter.setLightState(data);
        XLog.i("setLightState data: " + JSON.stringify(data));
    }

    static onQueryDeviceInfo(data){
        try{
            XLog.d("onQueryDeviceInfo:", data.index, "|", data.id);
            DataCenter.updateLocalCabinetLoops(data);
            let reportDeviceInfo = DataCenter.getCabinetDeviceInfo(data.id, ValidType.VALID);
            if(!reportDeviceInfo) {
                return;
            }
            CommunicationManager.send2Remote(formatterSendTopic(Topic_Property),
                commonMakeMqttRequest(ACK_Type.ACK, reportDeviceInfo, Topic_Property.method));
            CommunicationManager.send2Master(formatterSendTopic(Topic_Property),
                commonMakeMqttRequest(ACK_Type.NO_ACK, DataCenter.getLocalCabinetDeviceInfo(), Topic_Property.method));
        }catch(error) {
            XLog.e("onQueryDeviceInfo exception:",error?.message);
        }
    }

    static onSerialTimeout(data){
        DataCenter.updateInvalidState(data);
        let reportDeviceInfo = DataCenter.getCabinetDeviceInfo(data.id, ValidType.VALID);
        if(!reportDeviceInfo) {
            return;
        }
        CommunicationManager.send2Remote(formatterSendTopic(Topic_Property),
            commonMakeMqttRequest(ACK_Type.ACK, reportDeviceInfo, Topic_Property.method));
        CommunicationManager.send2Master(formatterSendTopic(Topic_Property),
            commonMakeMqttRequest(ACK_Type.NO_ACK, DataCenter.getLocalCabinetDeviceInfo(), Topic_Property.method));
    }
    
    static isSelfSendMessage(data) {
        return data?.gateId == DataCenter.gateId;
    }

    static onRemoteMqttLightMode(data){
        // console.log("onRemoteMqttLightMode: ", data);
        try{
            if(CommandManager.isSelfSendMessage(data)){
                // DataCenter.setLightMode(data.lightMode);
                SerialPortManager.setLightMode(data.lightMode);
                CommunicationManager.send2Remote(formatterSendTopic(Topic_Update_LightMode_Reply),
                    commonMakeRsp2Request(DataCenter.getLightMode().value, Topic_Property.method));
            }
        }catch(error) {
            XLog.e("onRemoteMqttLightMode exception:",error?.message);
        }
    }

    static onUpdateMqttProperty(data){
        try{
            console.log("onUpdateMqttProperty: ", data);
            if(CommandManager.isSelfSendMessage(data)) {
                return;
            }
            DataCenter.setCabinetDeviceInfo(data);
        }catch(error) {
            XLog.e("onUpdateMqttProperty exception:",error?.message);
        }
    }

    static onUpdateMqttDebugOperation(data){
        try{
            console.log("onUpdateMqttDebugOperation: ", data);
            DeviceEventEmitter.emit("debug", data);   
        }catch(error) {
            XLog.e("onUpdateMqttDebugOperation exception:",error?.message);
        }   
    }

    static onLocalMqttStrategy(data) {
        //master收到策略请求
        try{
            console.log("onLocalMqttStrategy", data);
            if(CommandManager.isSelfSendMessage(data)) {
                return;
            }
            CommunicationManager.send2Master(formatterSendTopic(Topic_Strategy_Reply),
                    commonMakeRsp2Request(DataCenter.getStrategyOriginData(), Topic_Strategy_Reply.method));
        }catch(error) {
            XLog.e("onLocalMqttStrategy exception:",error?.message);
        }
    }

    static onLocalMqttTunnel(data) {
        //master收到单洞请求
        try{
            console.log("onLocalMqttTunnel", data);
            if(CommandManager.isSelfSendMessage(data)) {
                return;
            }
            CommunicationManager.send2Master(formatterSendTopic(Topic_Tunnel_Reply),
                commonMakeRsp2Request(DataCenter.getTunnelOriginData(), Topic_Tunnel_Reply.method));
        }catch(error) {
            XLog.e("onLocalMqttTunnel exception:",error?.message);
        }
    }

    static onLocalMqttLoop(data) {
        //master收到集群请求
        try{
            console.log("onLocalMqttLoop", data);
            if(CommandManager.isSelfSendMessage(data)) {
                return;
            }
            CommunicationManager.send2Master(formatterSendTopic(Topic_Loop_Reply),
                commonMakeRsp2Request(DataCenter.getColonyOriginData(), Topic_Loop_Reply.method));
        }catch(error) {
            XLog.e("onLocalMqttLoop exception:",error?.message);
        }
    }

    static onLocalMqttAsync(data) {
        try{
            console.log("onLocalMqttAsync", data);
            CommunicationManager.send2Master(formatterTopic(Topic_Async_Reply, data.serverId, data.gateId),
                commonMakeRsp2Request(DataCenter.getGateValuesData(), Topic_Async_Reply.method));
        }catch(error) {
            XLog.e("onLocalMqttAsync exception:",error?.message);
        }
    }

    static onLocalMqttAsyncReply(data) {
        try{
            console.log("onLocalMqttAsyncReply", data);
            DataCenter.setGateValuesData(data);
        }catch(error) {
            XLog.e("onLocalMqttAsyncReply exception:",error?.message);
        }
    }

    // static onLocalMqttLightMode(data){
    //     if(CommandManager.isSelfSendMessage(data)){
    //         DataCenter.setLightMode(data.lightmode);
    //         CommunicationManager.send2Master(formatterSendTopic(Topic_Update_LightMode_Reply),
    //             commonMakeRsp2Request(1, Topic_Property.method));
    //     }
    // }
    static async onUpdateMqttMeterConfig(data) {
        try{
            console.log("onUpdateMqttMeterConfig", data);
            if(!CommandManager.isSelfSendMessage(data)) {//不是发给我的消息，丢弃
                return;
            }
            if(data.loopController){
                DataCenter.initLoopControllerList(data.loopController);
                await SerialPortManager.removeAllDevice(ProductID.LOOP);
                SerialPortManager.createDevice(ProductID.LOOP, DataCenter.loopControllerList);
            }
            if(data.smartMeter){
                DataCenter.initSmartMeterList(data.smartMeter);
                await SerialPortManager.removeAllDevice(ProductID.SMART);
                SerialPortManager.createDevice(ProductID.SMART, DataCenter.smartMeterList);
            }
            if(data.smartMeterConf){
                DataCenter.setMeterConfigList(data.smartMeterConf)
            }
            // DataCenter.setMeterConfigList(data);
        }catch(error) {
            XLog.e("onUpdateMqttMeterConfig exception:",error?.message);
        }
    }

    static onMeterRealtime(data){
        try{
            DataCenter.updateSmartMeterData(parserSmartMeter(data.message));
            let param = commonMakeMeterRequest(data.id, data.message, "jt_smart_meter_property", Topic_Meter_Property.method);
            console.log("onMeterRealtime: ", param);
            CommunicationManager.send2Remote(formatterSendTopic(Topic_Meter_Property),param);
        }catch(error) {
            XLog.e("onMeterRealtime exception:",error?.message);
        }
    }

    static onMeterStat(data){ 
        try{
            DataCenter.updateSmartMeterData(parserSmartMeter(data.message));
            let param = commonMakeMeterRequest(data.id, data.message, "jt_smart_meter_statistic", Topic_Meter_Property.method);
            console.log("onMeterStat: ", param);
            CommunicationManager.send2Remote(formatterSendTopic(Topic_Meter_Property),param);
        }catch(error) {
            XLog.e("onMeterStat exception:",error?.message);
        }            
    }
    
}